package com.ynsj.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.ynsj.domain.SysMenu;
import com.ynsj.feign.JwtToken;
import com.ynsj.feign.OAuth2FeignClient;
import com.ynsj.model.LoginResult;
import com.ynsj.service.SysLoginService;
import com.ynsj.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysLoginServiceImpl implements SysLoginService {

    @Autowired
    private OAuth2FeignClient oAuth2FeignClient;

    @Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
    private String basicToken;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    /**
     * 登录的实现
     * @param username 用户名称
     * @param password 用户密码
     * @return
     */
    @Override
    public LoginResult login(String username, String password) {
        log.info("用户{}开始登录",username);
        //1.获取token,需要远程调用authorization-server
        ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", username, password, "admin_type", basicToken);
        if(tokenResponseEntity.getStatusCode()!= HttpStatus.OK){
            throw new ApiException(ApiErrorCode.FAILED);
        }
        JwtToken jwtToken = tokenResponseEntity.getBody();
        log.info("远程调用授权服务器成功,获取的token为:{}",JSON.toJSONString(jwtToken,true));
        String token = jwtToken.getAccessToken();
        Jwt jwt = JwtHelper.decode(token);//解析jwt token
        String jwtTokenStr = jwt.getClaims();//获取到jwt荷载
        JSONObject jwtTokenJson = JSON.parseObject(jwtTokenStr);
        Long userId = jwtTokenJson.getLong("user_name");
        //2.查询用户的菜单数据
        List<SysMenu> menus = sysMenuService.getMenusByUserId(userId);
        //3.查询用户的权限数据
        JSONArray authoritiesJsonArray = JSON.parseArray(jwtTokenJson.getString("authorities"));
        List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream()//组装权限数据
                .map(authority->new SimpleGrantedAuthority(authority.toString())).collect(Collectors.toList());
        //1.将该token存储在Redis里面，配置我们的网关做jwt验证的操作
        redisTemplate.opsForValue().set(token,"",jwtToken.getExpiresIn(), TimeUnit.SECONDS);
        //2我们返回给前端的token数据少一个 bearer
        return new LoginResult(jwtToken.getTokenType()+" "+token,menus,authorities);
    }
}
